home *** CD-ROM | disk | FTP | other *** search
/ Programming Microsoft Visual Basic .NET / Programming Microsoft Visual Basic .NET (Microsoft Press)(X08-78517)(2002).bin / setup / vbnet / 21 adonet disconnected / adonetdisconnected / conflictform.vb < prev    next >
Encoding:
Text File  |  2002-03-16  |  37.2 KB  |  875 lines

  1. Imports System.Data
  2. Imports System.Data.OleDb
  3. Imports System.Data.SqlClient
  4.  
  5. Public Class ConflictForm
  6.     Inherits System.Windows.Forms.Form
  7.  
  8. #Region " Windows Form Designer generated code "
  9.  
  10.     Public Sub New()
  11.         MyBase.New()
  12.  
  13.         'This call is required by the Windows Form Designer.
  14.         InitializeComponent()
  15.  
  16.         'Add any initialization after the InitializeComponent() call
  17.  
  18.     End Sub
  19.  
  20.     'Form overrides dispose to clean up the component list.
  21.     Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
  22.         If disposing Then
  23.             If Not (components Is Nothing) Then
  24.                 components.Dispose()
  25.             End If
  26.         End If
  27.         MyBase.Dispose(disposing)
  28.     End Sub
  29.     Friend WithEvents DataGrid1 As System.Windows.Forms.DataGrid
  30.  
  31.     'Required by the Windows Form Designer
  32.     Private components As System.ComponentModel.Container
  33.  
  34.     'NOTE: The following procedure is required by the Windows Form Designer
  35.     'It can be modified using the Windows Form Designer.  
  36.     'Do not modify it using the code editor.
  37.     Friend WithEvents btnShowRows As System.Windows.Forms.Button
  38.     Friend WithEvents btnRunTransaction As System.Windows.Forms.Button
  39.     Friend WithEvents btnResync As System.Windows.Forms.Button
  40.     Friend WithEvents btnRowByRowResync As System.Windows.Forms.Button
  41.     Friend WithEvents btnUseRowUpdating As System.Windows.Forms.Button
  42.     <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
  43.         Me.DataGrid1 = New System.Windows.Forms.DataGrid()
  44.         Me.btnShowRows = New System.Windows.Forms.Button()
  45.         Me.btnRunTransaction = New System.Windows.Forms.Button()
  46.         Me.btnResync = New System.Windows.Forms.Button()
  47.         Me.btnRowByRowResync = New System.Windows.Forms.Button()
  48.         Me.btnUseRowUpdating = New System.Windows.Forms.Button()
  49.         CType(Me.DataGrid1, System.ComponentModel.ISupportInitialize).BeginInit()
  50.         Me.SuspendLayout()
  51.         '
  52.         'DataGrid1
  53.         '
  54.         Me.DataGrid1.Anchor = (((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
  55.                     Or System.Windows.Forms.AnchorStyles.Left) _
  56.                     Or System.Windows.Forms.AnchorStyles.Right)
  57.         Me.DataGrid1.DataMember = ""
  58.         Me.DataGrid1.HeaderForeColor = System.Drawing.SystemColors.ControlText
  59.         Me.DataGrid1.Location = New System.Drawing.Point(152, 16)
  60.         Me.DataGrid1.Name = "DataGrid1"
  61.         Me.DataGrid1.Size = New System.Drawing.Size(512, 328)
  62.         Me.DataGrid1.TabIndex = 0
  63.         '
  64.         'btnShowRows
  65.         '
  66.         Me.btnShowRows.Location = New System.Drawing.Point(8, 16)
  67.         Me.btnShowRows.Name = "btnShowRows"
  68.         Me.btnShowRows.Size = New System.Drawing.Size(128, 40)
  69.         Me.btnShowRows.TabIndex = 2
  70.         Me.btnShowRows.Text = "Show Conflicting Rows"
  71.         '
  72.         'btnRunTransaction
  73.         '
  74.         Me.btnRunTransaction.Location = New System.Drawing.Point(8, 160)
  75.         Me.btnRunTransaction.Name = "btnRunTransaction"
  76.         Me.btnRunTransaction.Size = New System.Drawing.Size(128, 40)
  77.         Me.btnRunTransaction.TabIndex = 3
  78.         Me.btnRunTransaction.Text = "Run in Transaction"
  79.         '
  80.         'btnResync
  81.         '
  82.         Me.btnResync.Location = New System.Drawing.Point(8, 64)
  83.         Me.btnResync.Name = "btnResync"
  84.         Me.btnResync.Size = New System.Drawing.Size(128, 40)
  85.         Me.btnResync.TabIndex = 4
  86.         Me.btnResync.Text = "Resync conflicting rows"
  87.         '
  88.         'btnRowByRowResync
  89.         '
  90.         Me.btnRowByRowResync.Location = New System.Drawing.Point(8, 112)
  91.         Me.btnRowByRowResync.Name = "btnRowByRowResync"
  92.         Me.btnRowByRowResync.Size = New System.Drawing.Size(128, 40)
  93.         Me.btnRowByRowResync.TabIndex = 5
  94.         Me.btnRowByRowResync.Text = "Row-by-row resync"
  95.         '
  96.         'btnUseRowUpdating
  97.         '
  98.         Me.btnUseRowUpdating.Location = New System.Drawing.Point(8, 208)
  99.         Me.btnUseRowUpdating.Name = "btnUseRowUpdating"
  100.         Me.btnUseRowUpdating.Size = New System.Drawing.Size(128, 40)
  101.         Me.btnUseRowUpdating.TabIndex = 6
  102.         Me.btnUseRowUpdating.Text = "RowUpdating Event"
  103.         '
  104.         'ConflictForm
  105.         '
  106.         Me.AutoScaleBaseSize = New System.Drawing.Size(7, 17)
  107.         Me.ClientSize = New System.Drawing.Size(672, 349)
  108.         Me.Controls.AddRange(New System.Windows.Forms.Control() {Me.btnUseRowUpdating, Me.btnRowByRowResync, Me.btnResync, Me.btnRunTransaction, Me.btnShowRows, Me.DataGrid1})
  109.         Me.Font = New System.Drawing.Font("Microsoft Sans Serif", 11.0!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
  110.         Me.Name = "ConflictForm"
  111.         Me.Text = "Conflict Detection"
  112.         CType(Me.DataGrid1, System.ComponentModel.ISupportInitialize).EndInit()
  113.         Me.ResumeLayout(False)
  114.  
  115.     End Sub
  116.  
  117. #End Region
  118.  
  119.     ' This form only works with SQL Server's Pubs database.
  120.     ' ensure that only Const is -1
  121. #Const OLEDBPUBS = -1
  122. #Const SQLPUBS = 0
  123.  
  124.     Dim ds As New DataSet()
  125.  
  126.     ' show the Publishers table
  127.  
  128.     Private Sub btnShowRows_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnShowRows.Click
  129.         Dim sql As String = "SELECT * FROM Publishers"
  130.  
  131. #If OLEDBPUBS Then
  132.         Dim cn As New OleDbConnection(OledbPubsConnString)
  133.         Dim da As New OleDbDataAdapter(sql, cn)
  134.         Dim cmd As OleDbCommand
  135. #ElseIf SQLPUBS Then
  136.         Dim cn As New SqlConnection(SqlPubsConnString)
  137.         Dim da As New SqlDataAdapter(sql, cn)
  138.         dim cmd as SqlCommand
  139. #End If
  140.  
  141.         cn.Open()
  142.         If ds.Tables.Contains("Publishers") Then ds.Tables("Publishers").Clear()
  143.         da.FillSchema(ds, SchemaType.Source, "Publishers")
  144.         da.Fill(ds, "Publishers")
  145.  
  146.         DataGrid1.DataSource = ds.Tables("Publishers")
  147.  
  148. #If OLEDBPUBS Then
  149.         Dim cmdBuilder As New OleDbCommandBuilder(da)
  150.         Dim par As OleDbParameter
  151. #ElseIf SQLPUBS Then
  152.         Dim cmdBuilder As New SqlCommandBuilder(da)
  153.         Dim par As SqlParameter
  154. #End If
  155.  
  156.         ' generate the three commands
  157.         da.DeleteCommand = cmdBuilder.GetDeleteCommand
  158.         da.InsertCommand = cmdBuilder.GetInsertCommand
  159.         da.UpdateCommand = cmdBuilder.GetUpdateCommand
  160.  
  161.         ' Display info on auto-generated commands
  162.         Debug.WriteLine(da.InsertCommand.CommandText)
  163.         Debug.WriteLine(da.UpdateCommand.CommandText)
  164.         Debug.WriteLine(da.DeleteCommand.CommandText)
  165.         For Each par In da.UpdateCommand.Parameters
  166.             Debug.WriteLine(par.ParameterName & " => " & par.SourceColumn & "(" & par.SourceVersion.ToString & ")")
  167.         Next
  168.  
  169.         ' Send a command that modifies the pub_name of first row
  170.         cmd = cn.CreateCommand
  171.         cmd.CommandText = "UPDATE Publishers SET pub_name ='" & ds.Tables("Publishers").Rows(0)("pub_name").ToString & " (mod)' WHERE Pub_id='" _
  172.             & ds.Tables("Publishers").Rows(0)("pub_id").ToString & "'"
  173.         cmd.ExecuteNonQuery()
  174.  
  175.         ' modify the local copy of the data.
  176.         With ds.Tables("Publishers")
  177.             ' Modify the first record (this fails because this record has changed)
  178.             .Rows(0)("pub_name") = .Rows(0)("pub_name").ToString & " (new)"
  179.             ' Add a new record (this fails because there is already a record with this key)
  180.             Dim newdr As DataRow = .NewRow
  181.             newdr("pub_id") = "9999"
  182.             newdr("pub_name") = "Vb2TheMax"
  183.             newdr("city") = "Bari"
  184.             newdr("country") = "Italy"
  185.             .Rows.Add(newdr)
  186.             ' delete the second row. (this fails because of RI constraints)
  187.             .Rows(1).Delete()
  188.         End With
  189.  
  190.         ' Ensure that all conflict are ignored, so that the application
  191.         ' attempts to update all rows.
  192.         da.ContinueUpdateOnError = True
  193.         da.Update(ds, "Publishers")
  194.         cn.Close()
  195.  
  196.         ' exit if the attempt was successfull
  197.         If Not ds.HasChanges Then Exit Sub
  198.  
  199.         ' Not all rows were updated successfully.
  200.         Dim dt As DataTable = ds.Tables("Publishers")
  201.  
  202.         ' Here's a simple way to evaluate the number of conflicting rows.
  203.         Dim rowCount As Integer = dt.GetChanges().Rows.Count
  204.  
  205.         ' This block of code shows how to mark conflicting rows
  206.         ' without attempting to resync them with the data source.
  207.  
  208.         ' Mark all conflicting row with proper error message.
  209.         Dim dr As DataRow
  210.         For Each dr In dt.Rows
  211.             If dr.RowState = DataRowState.Added Then
  212.                 dr.RowError = "Failed INSERT operation"
  213.             ElseIf dr.RowState = DataRowState.Modified Then
  214.                 dr.RowError = "Failed UPDATE operation"
  215.             ElseIf dr.RowState = DataRowState.Deleted Then
  216.                 dr.RowError = "Failed DELETE operation"
  217.                 ' Undelete this record, otherwise it wouldn't show in the table.
  218.                 dr.RejectChanges()
  219.             End If
  220.         Next
  221.     End Sub
  222.  
  223.     ' demonstrates how to run updates inside a transaction
  224.  
  225.     Private Sub btnRunTransaction_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRunTransaction.Click
  226.         Dim sql As String = "SELECT * FROM Publishers"
  227.  
  228. #If OLEDBPUBS Then
  229.         Dim cn As New OleDbConnection(OledbPubsConnString)
  230.         Dim da As New OleDbDataAdapter(sql, cn)
  231.         Dim cmd As OleDbCommand
  232. #ElseIf SQLPUBS Then
  233.         Dim cn As New SqlConnection(SqlPubsConnString)
  234.         Dim da As New SqlDataAdapter(sql, cn)
  235.         dim cmd as SqlCommand
  236. #End If
  237.  
  238.         cn.Open()
  239.         If ds.Tables.Contains("Publishers") Then ds.Tables("Publishers").Clear()
  240.         'da.FillSchema(ds, SchemaType.Source, "Publishers")
  241.         da.Fill(ds, "Publishers")
  242.  
  243.         DataGrid1.DataSource = ds.Tables("Publishers")
  244.  
  245. #If OLEDBPUBS Then
  246.         Dim cmdBuilder As New OleDbCommandBuilder(da)
  247.         Dim par As OleDbParameter
  248.  
  249. #ElseIf SQLPUBS Then
  250.         Dim cmdBuilder As New SqlCommandBuilder(da)
  251.         Dim par As SqlParameter
  252. #End If
  253.  
  254.         ' generate the three default command
  255.         da.DeleteCommand = cmdBuilder.GetDeleteCommand
  256.         da.InsertCommand = cmdBuilder.GetInsertCommand
  257.         da.UpdateCommand = cmdBuilder.GetUpdateCommand
  258.  
  259.         ' Send a command that modifies the pub_name of first row
  260.         cmd = cn.CreateCommand
  261.         cmd.CommandText = "UPDATE Publishers SET pub_name ='" & ds.Tables("Publishers").Rows(0)("pub_name").ToString & " (mod)' WHERE Pub_id='" _
  262.             & ds.Tables("Publishers").Rows(0)("pub_id").ToString & "'"
  263.         cmd.ExecuteNonQuery()
  264.  
  265.         ' modify the local copy of the data.
  266.         With ds.Tables("Publishers")
  267.             ' Modify the first record (this fails because this record has changed)
  268.             .Rows(0)("pub_name") = .Rows(0)("pub_name").ToString & " (new)"
  269.             ' Add a new record (this fails because there is already a record with this key)
  270.             Dim newdr As DataRow = .NewRow
  271.             newdr("pub_id") = "9999"
  272.             newdr("pub_name") = "Vb2TheMax"
  273.             newdr("city") = "Bari"
  274.             newdr("country") = "Italy"
  275.             .Rows.Add(newdr)
  276.             ' delete the second row. (this fails because of RI constraints)
  277.             .Rows(1).Delete()
  278.         End With
  279.  
  280.         ' Run the Update method inside a transaction
  281.         Dim tr As OleDbTransaction
  282.         tr = cn.BeginTransaction()
  283.  
  284.         ' Enroll all the update commands inside the same transaction.
  285.         da.UpdateCommand.Transaction = tr
  286.         da.DeleteCommand.Transaction = tr
  287.         da.InsertCommand.Transaction = tr
  288.  
  289.         ' Send changes them to the database.
  290.         Try
  291.             da.Update(ds, "Publishers")
  292.             ' commit if everything was OK
  293.             tr.Commit()
  294.         Catch ex As Exception
  295.             ' Rollback the transaction, if there is one.
  296.             If Not (tr Is Nothing) Then
  297.                 tr.Rollback()
  298.                 ' Let the user know that there was a problem.
  299.                 MessageBox.Show(ex.Message, "Update error", MessageBoxButtons.OK, MessageBoxIcon.Error)
  300.             End If
  301.         End Try
  302.         cn.Close()
  303.     End Sub
  304.  
  305.     ' resync with the data source
  306.  
  307.     Private Sub btnResync_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnResync.Click
  308.         Dim sql As String = "SELECT * FROM Publishers"
  309.  
  310. #If OLEDBPUBS Then
  311.         Dim cn As New OleDbConnection(OledbPubsConnString)
  312.         Dim da As New OleDbDataAdapter(sql, cn)
  313.         Dim cmd As OleDbCommand
  314. #ElseIf SQLPUBS Then
  315.         Dim cn As New SqlConnection(SqlPubsConnString)
  316.         Dim da As New SqlDataAdapter(sql, cn)
  317.         dim cmd as SqlCommand
  318. #End If
  319.  
  320.         cn.Open()
  321.         If ds.Tables.Contains("Publishers") Then ds.Tables("Publishers").Clear()
  322.         'da.FillSchema(ds, SchemaType.Source, "Publishers")
  323.         da.Fill(ds, "Publishers")
  324.  
  325.         DataGrid1.DataSource = ds.Tables("Publishers")
  326.  
  327. #If OLEDBPUBS Then
  328.         Dim cmdBuilder As New OleDbCommandBuilder(da)
  329.         Dim par As OleDbParameter
  330. #ElseIf SQLPUBS Then
  331.         Dim cmdBuilder As New SqlCommandBuilder(da)
  332.         Dim par As SqlParameter
  333. #End If
  334.  
  335.         da.DeleteCommand = cmdBuilder.GetDeleteCommand
  336.         da.InsertCommand = cmdBuilder.GetInsertCommand
  337.         da.UpdateCommand = cmdBuilder.GetUpdateCommand
  338.  
  339.         ' Send a command that modifies the pub_name of first row
  340.         cmd = cn.CreateCommand
  341.         cmd.CommandText = "UPDATE Publishers SET pub_name ='" & ds.Tables("Publishers").Rows(0)("pub_name").ToString & " (mod)' WHERE Pub_id='" _
  342.             & ds.Tables("Publishers").Rows(0)("pub_id").ToString & "'"
  343.         cmd.ExecuteNonQuery()
  344.  
  345.         ' modify the local copy of the data.
  346.         With ds.Tables("Publishers")
  347.             ' Modify the first record (this fails because this record has changed)
  348.             .Rows(0)("pub_name") = .Rows(0)("pub_name").ToString & " (new)"
  349.             ' Add a new record (this fails because there is already a record with this key)
  350.             Dim newdr As DataRow = .NewRow
  351.             newdr("pub_id") = "9999"
  352.             newdr("pub_name") = "Vb2TheMax"
  353.             newdr("city") = "Bari"
  354.             newdr("country") = "Italy"
  355.             .Rows.Add(newdr)
  356.             ' delete the second row. (this fails because of RI constraints)
  357.             .Rows(1).Delete()
  358.         End With
  359.  
  360.         ' Ensure that all conflict are ignored, so that the application
  361.         ' attempts to update all rows.
  362.         da.ContinueUpdateOnError = True
  363.         da.Update(ds, "Publishers")
  364.         cn.Close()
  365.  
  366.         ' exit if the attempt was successfull
  367.         If Not ds.HasChanges Then Exit Sub
  368.  
  369.         ' Not all rows were updated successfully.
  370.         Dim dt As DataTable = ds.Tables("Publishers")
  371.  
  372.         ' This block of code shows how to mark conflicting rows and
  373.         ' doing a resynch with the data source.
  374.  
  375.         ' Keeping key column name in a variable helps make this code reusable.
  376.         Dim keyName As String = "pub_id"
  377.  
  378.         ' Build the list of the key values for all these rows.
  379.         Dim values As New System.Text.StringBuilder(1000)
  380.         Dim keyValue As String
  381.         Dim dr As DataRow
  382.  
  383.         For Each dr In dt.Rows
  384.             ' Only consider modified rows.
  385.             If dr.RowState <> DataRowState.Unchanged Then
  386.                 ' The key to be used depends on the row state.
  387.                 If dr.RowState = DataRowState.Added Then
  388.                     ' Use the current key for inserted rows.
  389.                     keyValue = dr(keyName, DataRowVersion.Current).ToString
  390.                 Else
  391.                     ' Use the original key for deleted and modified rows.
  392.                     keyValue = dr(keyName, DataRowVersion.Original).ToString
  393.                 End If
  394.                 ' Append to the list of keys
  395.                 If values.Length > 0 Then values.Append(",")
  396.                 values.Append("'")
  397.                 values.Append(keyValue)
  398.                 values.Append("'")
  399.             End If
  400.         Next
  401.  
  402.         ' Create a new SELECT with only these records, using the DataAdapter
  403.         ' SELECT command as a template
  404.         Dim sql2 As String = da.SelectCommand.CommandText
  405.         ' Delete the WHERE clause, if there is one.
  406.         Dim k As Integer = sql2.ToUpper.IndexOf(" WHERE ")
  407.         If k > 0 Then sql2 = sql2.Substring(0, k - 1)
  408.         ' Add the WHERE clause that contains the list of all key values.
  409.         sql2 &= " WHERE " & keyName & " IN (" & values.ToString & ")"
  410.  
  411.         ' Read again only the conflicting rows.
  412. #If OLEDBPUBS Then
  413.         Dim da2 As New OleDbDataAdapter(sql2, cn)
  414. #ElseIf SQLPUBS Then
  415.         Dim da2 As New SqlDataAdapter(sql2, cn)
  416. #End If
  417.         ' Fill a new DataTable (it doesn't have to belong to the DataSet).
  418.         Dim dt2 As New DataTable()
  419.         da2.Fill(dt2)
  420.  
  421.         ' Loop on all the rows that failed to update.
  422.         Dim dr2 As DataRow
  423.         For Each dr In dt.Rows
  424.             If dr.RowState <> DataRowState.Unchanged Then
  425.                 ' Mark the row with a proper error message, get the key to be
  426.                 ' used for searching in DT2.
  427.                 If dr.RowState = DataRowState.Added Then
  428.                     dr.RowError = "Failed INSERT command"
  429.                     keyValue = dr(keyName, DataRowVersion.Current).ToString
  430.                 ElseIf dr.RowState = DataRowState.Deleted Then
  431.                     dr.RowError = "Failed DELETE command"
  432.                     keyValue = dr(keyName, DataRowVersion.Original).ToString
  433.                 ElseIf dr.RowState = DataRowState.Modified Then
  434.                     dr.RowError = "Failed UPDATE command"
  435.                     keyValue = dr(keyName, DataRowVersion.Original).ToString
  436.                 End If
  437.  
  438.                 ' Get the matching row in the new table.
  439.                 Dim rows() As DataRow = dt2.Select(keyName & "='" & keyValue & "'")
  440.                 If (rows Is Nothing) OrElse rows.Length = 0 Then
  441.                     ' We can't find the conflicting row in the database.
  442.                     dr.RowError &= " - Unable to resync with data source"
  443.                     ' Check whether the user changed the primary key.
  444.                     If dr.RowState <> DataRowState.Added AndAlso dr(keyName, DataRowVersion.Current).ToString <> dr(keyName, DataRowVersion.Original).ToString Then
  445.                         ' This is a probable source of the conflict.
  446.                         dr.SetColumnError(keyName, "Modified primary key")
  447.                     End If
  448.  
  449.                 Else
  450.                     ' We have found the conflicting row in the database, so
  451.                     ' we can compare values now in each column.
  452.                     dr2 = rows(0)
  453.  
  454.                     Dim i As Integer
  455.                     For i = 0 To dr.Table.Columns.Count - 1
  456.                         ' The comparisons we do depend on the row state.
  457.                         If dr.RowState = DataRowState.Added Then
  458.                             ' For inserted rows we can compare current value with database value.
  459.                             If dr(i).ToString <> dr2(i).ToString Then
  460.                                 ' Show the value now in database.
  461.                                 dr.SetColumnError(i, "Value in database = " & dr2(i).ToString)
  462.                             End If
  463.                         Else
  464.                             ' For deleted and modified rows we can compare original value with database value.
  465.                             If dr(i, DataRowVersion.Original).ToString <> dr2(i).ToString Then
  466.                                 Dim msg As String = ""
  467.                                 If dr(i, DataRowVersion.Original).ToString <> dr(i).ToString Then
  468.                                     msg = "Original value = " & dr(i).ToString & ", "
  469.                                 End If
  470.                                 msg &= "Value in database = " & dr2(i).ToString
  471.                                 dr.SetColumnError(i, msg)
  472.                             End If
  473.                         End If
  474.                     Next
  475.  
  476.                 End If
  477.             End If
  478.  
  479.             ' If this is a deleted row, reject changes to make it visible in table.
  480.             If dr.RowState = DataRowState.Deleted Then
  481.                 dr.RejectChanges()
  482.             End If
  483.         Next
  484.     End Sub
  485.  
  486.     ' demonstrate a row-by-row resync
  487.  
  488.     Private Sub btnRowByRowResync_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRowByRowResync.Click
  489.         Dim sql As String = "SELECT * FROM Publishers"
  490.  
  491. #If OLEDBPUBS Then
  492.         Dim cn As New OleDbConnection(OledbPubsConnString)
  493.         Dim da As New OleDbDataAdapter(sql, cn)
  494.         Dim cmd As OleDbCommand
  495. #Else
  496.         Dim cn As New SqlConnection(SqlPubsConnString)
  497.         Dim da As New SqlDataAdapter(sql, cn)
  498.         dim cmd as SqlCommand
  499. #End If
  500.  
  501.         cn.Open()
  502.         If ds.Tables.Contains("Publishers") Then ds.Tables("Publishers").Clear()
  503.         'da.FillSchema(ds, SchemaType.Source, "Publishers")
  504.         da.Fill(ds, "Publishers")
  505.  
  506.         DataGrid1.DataSource = ds.Tables("Publishers")
  507.  
  508. #If OLEDBPUBS Then
  509.         Dim cmdBuilder As New OleDbCommandBuilder(da)
  510.         Dim par As OleDbParameter
  511.  
  512. #ElseIf SQLPUBS Then
  513.         Dim cmdBuilder As New SqlCommandBuilder(da)
  514.         Dim par As SqlParameter
  515. #End If
  516.  
  517.         da.DeleteCommand = cmdBuilder.GetDeleteCommand
  518.         da.InsertCommand = cmdBuilder.GetInsertCommand
  519.         da.UpdateCommand = cmdBuilder.GetUpdateCommand
  520.  
  521.         ' Send a command that modifies the pub_name of first row
  522.         cmd = cn.CreateCommand
  523.         cmd.CommandText = "UPDATE Publishers SET pub_name ='" & ds.Tables("Publishers").Rows(0)("pub_name").ToString & " (mod)' WHERE Pub_id='" _
  524.             & ds.Tables("Publishers").Rows(0)("pub_id").ToString & "'"
  525.         cmd.ExecuteNonQuery()
  526.  
  527.         ' modify the local copy of the data.
  528.         With ds.Tables("Publishers")
  529.             ' Modify the first record (this fails because this record has changed)
  530.             .Rows(0)("pub_name") = .Rows(0)("pub_name").ToString & " (new)"
  531.             ' Add a new record (this fails because there is already a record with this key)
  532.             Dim newdr As DataRow = .NewRow
  533.             newdr("pub_id") = "9999"
  534.             newdr("pub_name") = "Vb2TheMax"
  535.             newdr("city") = "Bari"
  536.             newdr("country") = "Italy"
  537.             .Rows.Add(newdr)
  538.             ' delete the second row. (this fails because of RI constraints)
  539.             .Rows(1).Delete()
  540.         End With
  541.  
  542.         ' Prepare the Command that reads a single row.
  543.         resyncCmd = GetCurrentRowCommand(da, ds.Tables("Publishers").Columns("pub_id"))
  544.  
  545.         ' Ensure that all conflict are ignored, so that the application
  546.         ' attempts to update all rows.
  547.         AddHandler da.RowUpdated, AddressOf OnRowUpdated_Resync
  548.         da.Update(ds, "Publishers")
  549.         cn.Close()
  550.     End Sub
  551.  
  552.     ' Retrieve a single record from a table.
  553.     Function GetCurrentRowCommand(ByVal da As OleDbDataAdapter, ByVal ParamArray keyColumns() As DataColumn) As OleDbCommand
  554.         ' Get the SELECT statement in the DataAdapter 
  555.         Dim sql As String = da.SelectCommand.CommandText
  556.         ' Truncate the statement just before the WHERE clause, if there is one.
  557.         Dim i As Integer = sql.ToUpper.IndexOf("WHERE ")
  558.         If i > 0 Then sql = sql.Substring(0, i - 1)
  559.  
  560.         ' Add the WHERE clause on all primary key fields.
  561.         Dim dc As DataColumn
  562.         Dim sb As New System.Text.StringBuilder(100)
  563.         For Each dc In keyColumns
  564.             If sb.Length > 0 Then sb.Append(" AND ")
  565.             sb.Append("[")
  566.             'sql.Append (tmap.ColumnMappings.GetByDataSetColumn(dc.ColumnName).SourceColumn
  567.             sb.Append(dc.ColumnName)
  568.             sb.Append("]=?")
  569.         Next
  570.         sql &= " WHERE " & sb.ToString
  571.  
  572.         ' Create the command object on the same connection
  573. #If OLEDBPUBS Then
  574.         Dim cmd As New OleDbCommand(sql, CType(da.SelectCommand.Connection, OleDbConnection))
  575. #ElseIf SQLPUBS Then
  576.         Dim cmd As New SqlCommand(sql, CType(da.SelectCommand.Connection, SqlConnection))
  577. #End If
  578.         ' create the collection of parameters.
  579.         For Each dc In keyColumns
  580.             cmd.Parameters.Add(dc.ColumnName, dc.DataType)
  581.         Next
  582.  
  583.         ' Return the command
  584.         Return cmd
  585.     End Function
  586.  
  587.  
  588. #If OLEDBPUBS Then
  589.     ' This holds the command that does the row-by-row resync
  590.     Dim resyncCmd As OleDbCommand
  591.  
  592.     Sub OnRowUpdated_Resync(ByVal sender As Object, ByVal args As OleDbRowUpdatedEventArgs)
  593. #Else
  594.  
  595.     Dim resyncCmd As SqlCommand
  596.  
  597.     Sub OnRowUpdated_Resync(ByVal sender As Object, ByVal args As SqlRowUpdatedEventArgs)
  598. #End If
  599.         If args.Status <> UpdateStatus.ErrorsOccurred Then
  600.             ' Update was ok.
  601.         ElseIf Not TypeOf args.Errors Is DBConcurrencyException Then
  602.             ' An error occorred 
  603.             args.Row.RowError = "Failed to update: " & args.Errors.Message
  604.             ' Continue the update operation anyway.
  605.             args.Status = UpdateStatus.Continue
  606.         Else
  607.             ' An update conflict occurred.
  608.             Dim dr As DataRow = args.Row
  609.             Dim keyValue As String
  610.             Dim keyName As String = "pub_id"
  611.  
  612.             Select Case args.StatementType
  613.                 Case StatementType.Insert
  614.                     dr.RowError = "Conflict on an INSERT operation"
  615.                     keyValue = dr(keyName, DataRowVersion.Current).ToString
  616.                 Case StatementType.Delete
  617.                     dr.RowError = "Conflict on a DELETE operation"
  618.                     keyValue = dr(keyName, DataRowVersion.Original).ToString
  619.                 Case StatementType.Update
  620.                     dr.RowError = "Conflict on an UPDATE operation"
  621.                     keyValue = dr(keyName, DataRowVersion.Original).ToString
  622.             End Select
  623.  
  624.             ' read the current row - use the original key value, though.
  625.             ' (This is necessary otherwise you get an error if the row has been deleted)
  626.             resyncCmd.Parameters(keyName).Value = keyValue
  627.             ' we use IDataReader for db independence
  628.             Dim dre As IDataReader = resyncCmd.ExecuteReader(CommandBehavior.SingleRow)
  629.  
  630.             ' Advanced to first record, and remember whether there is a record.
  631.             Dim recordFound As Boolean = dre.Read
  632.  
  633.             If recordFound And args.StatementType = StatementType.Insert Then
  634.                 ' We attempted an insert on a record that is already there.
  635.                 dr.RowError &= "- There is already a record with key = " & keyValue
  636.             ElseIf Not recordFound And args.StatementType <> StatementType.Insert Then
  637.                 ' We attempted to update/delete a record that isn't there any longer
  638.                 dr.RowError &= "Can't find a matching record with key = " & keyValue
  639.             Else
  640.                 ' The operation failed for some other reason.
  641.                 ' In this demo we just print information on all changed columns.
  642.  
  643.                 ' At the end of the loop this variable is 0 only if the current value
  644.                 ' and the database value are the same for all conflicting columns
  645.                 Dim nonMatchingColumns As Integer = 0
  646.  
  647.                 Dim i As Integer
  648.                 For i = 0 To dre.FieldCount - 1
  649.                     Dim dbValue, origValue, currValue As Object
  650.                     ' Get current value in database, if there is a matching record.
  651.                     If recordFound Then
  652.                         dbValue = dre(i)
  653.                     End If
  654.                     ' Get original value, if not an Insert operation.
  655.                     If args.StatementType <> StatementType.Insert Then
  656.                         origValue = args.Row(i, DataRowVersion.Original)
  657.                     End If
  658.                     ' Get the current value, if not a Delete operation.
  659.                     If args.StatementType <> StatementType.Delete Then
  660.                         currValue = args.Row(i, DataRowVersion.Current)
  661.                     End If
  662.                     ' Decide whether this field might be a potential source for a conflict.
  663.                     Dim conflicting As Boolean = False
  664.  
  665.                     If Not recordFound Then
  666.                         ' If couldn't find the record, any modified column can be considered
  667.                         ' as a potential cause for conflict.
  668.                         If Not (origValue Is Nothing) AndAlso Not (currValue Is Nothing) AndAlso (origValue.ToString <> currValue.ToString) Then
  669.                             conflicting = True
  670.                         End If
  671.                     Else
  672.                         ' If the record was found, but the original and the database values 
  673.                         ' differ, then we've found a cause for the conflict.
  674.                         If Not (origValue Is Nothing) AndAlso (dbValue.ToString <> origValue.ToString) Then
  675.                             conflicting = True
  676.                             If Not (currValue Is Nothing) AndAlso (dbValue.ToString <> currValue.ToString) Then
  677.                                 ' We've found a column for which the database and current
  678.                                 ' values don't match.
  679.                                 nonMatchingColumns += 1
  680.                             End If
  681.                         End If
  682.                     End If
  683.  
  684.                     If conflicting Then
  685.                         ' Display field name and all related values.
  686.                         Dim msg As String = ""
  687.                         If Not (origValue Is Nothing) Then
  688.                             msg = "Original value = " & origValue.ToString & ","
  689.                         End If
  690.                         If Not (dbValue Is Nothing) Then
  691.                             msg &= "Value in database =" & dbValue.ToString
  692.                         End If
  693.                         dr.SetColumnError(i, msg)
  694.                     End If
  695.                 Next
  696.  
  697.                 ' If we've found a record in the database and all the values in the
  698.                 ' database match the current values, it means that we can consider
  699.                 ' this record as successfully updated, because another user had
  700.                 ' inserted exactly the same values that this user wanted to change.
  701.                 If recordFound And nonMatchingColumns = 0 Then
  702.                     dr.AcceptChanges()
  703.                     dr.ClearErrors()
  704.                 End If
  705.             End If
  706.  
  707.             ' Close the DataReader.
  708.             dre.Close()
  709.  
  710.             ' In all cases, swallow the exception and continue.
  711.             args.Status = UpdateStatus.Continue
  712.  
  713.         End If
  714.     End Sub
  715.  
  716.     ' demonstrate the RowUpdating event
  717.  
  718.     Private Sub btnUseRowUpdating_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnUseRowUpdating.Click
  719.         Dim sql As String = "SELECT * FROM Publishers"
  720.  
  721. #If OLEDBPUBS Then
  722.         Dim cn As New OleDbConnection(OledbPubsConnString)
  723.         Dim da As New OleDbDataAdapter(sql, cn)
  724.         Dim cmd As OleDbCommand
  725. #ElseIf SQLPUBS Then
  726.         Dim cn As New SqlConnection(SqlPubsConnString)
  727.         Dim da As New SqlDataAdapter(sql, cn)
  728.         dim cmd as SqlCommand
  729. #End If
  730.  
  731.         cn.Open()
  732.         If ds.Tables.Contains("Publishers") Then ds.Tables("Publishers").Clear()
  733.         'da.FillSchema(ds, SchemaType.Source, "Publishers")
  734.         da.Fill(ds, "Publishers")
  735.  
  736.         DataGrid1.DataSource = ds.Tables("Publishers")
  737.  
  738. #If OLEDBPUBS Then
  739.         Dim cmdBuilder As New OleDbCommandBuilder(da)
  740.         Dim par As OleDbParameter
  741.  
  742. #ElseIf SQLPUBS Then
  743.         Dim cmdBuilder As New SqlCommandBuilder(da)
  744.         Dim par As SqlParameter
  745. #End If
  746.  
  747.         da.DeleteCommand = cmdBuilder.GetDeleteCommand
  748.         da.InsertCommand = cmdBuilder.GetInsertCommand
  749.         da.UpdateCommand = cmdBuilder.GetUpdateCommand
  750.  
  751.         ' Send a command that modifies the pub_name of first row
  752.         cmd = cn.CreateCommand
  753.         cmd.CommandText = "UPDATE Publishers SET pub_name ='" & ds.Tables("Publishers").Rows(0)("pub_name").ToString & " (mod)' WHERE Pub_id='" _
  754.             & ds.Tables("Publishers").Rows(0)("pub_id").ToString & "'"
  755.         cmd.ExecuteNonQuery()
  756.  
  757.         ' modify the local copy of the data.
  758.         With ds.Tables("Publishers")
  759.             ' Modify the first record (this fails because this record has changed)
  760.             .Rows(0)("pub_name") = .Rows(0)("pub_name").ToString & " (new)"
  761.             ' Add a new record (this fails because there is already a record with this key)
  762.             Dim newdr As DataRow = .NewRow
  763.             newdr("pub_id") = "9999"
  764.             newdr("pub_name") = "Vb2TheMax"
  765.             newdr("city") = "Bari"
  766.             newdr("country") = "Italy"
  767.             .Rows.Add(newdr)
  768.             ' delete the second row. (this fails because of RI constraints)
  769.             .Rows(1).Delete()
  770.         End With
  771.  
  772.         ' Ensure that all conflict are ignored, so that the application
  773.         ' attempts to update all rows.
  774.         AddHandler da.RowUpdating, AddressOf OnRowUpdating
  775.         ' AddHandler da.RowUpdated, AddressOf OnRowUpdated_Continue
  776.         da.ContinueUpdateOnError = True
  777.         da.Update(ds, "Publishers")
  778.         cn.Close()
  779.  
  780.         ' exit if the attempt was successfull
  781.         If Not ds.HasChanges Then Exit Sub
  782.  
  783.         ' Not all rows were updated successfully.
  784.         Dim dt As DataTable = ds.Tables("Publishers")
  785.  
  786.         ' Here's a simple way to evaluate the number of conflicting rows.
  787.         Dim rowCount As Integer = dt.GetChanges().Rows.Count
  788.  
  789.         ' This block of code shows how to mark conflicting rows
  790.         ' without attempting to resync them with the data source.
  791.  
  792.         ' Mark all conflicting row with proper error message.
  793.         Dim dr As DataRow
  794.         For Each dr In dt.Rows
  795.             If dr.RowState = DataRowState.Added Then
  796.                 dr.RowError = "Failed INSERT operation"
  797.             ElseIf dr.RowState = DataRowState.Modified Then
  798.                 dr.RowError = "Failed UPDATE operation"
  799.             ElseIf dr.RowState = DataRowState.Deleted Then
  800.                 dr.RowError = "Failed DELETE operation"
  801.                 ' Undelete this record, otherwise it wouldn't show in the table.
  802.                 dr.RejectChanges()
  803.             End If
  804.         Next
  805.     End Sub
  806.  
  807.     ' this event fires before a command is sent to the db
  808.  
  809.     Sub OnRowUpdating(ByVal sender As Object, ByVal args As OleDbRowUpdatingEventArgs)
  810.         ' Exit if this isn't an Update operation.
  811.         If args.StatementType <> StatementType.Update Then Exit Sub
  812.  
  813.         Dim keyName As String = "pub_id"
  814.         Dim dr As DataRow = args.Row
  815.  
  816.         Dim i As Integer
  817.         Dim numColumns As Integer = dr.Table.Columns.Count
  818.         Dim setText As String = ""
  819.         Dim whereText As String = ""
  820.         Dim setParams As New ArrayList()
  821.         Dim whereParams As New ArrayList()
  822.         Dim param As OleDbParameter
  823.  
  824.         For i = 0 To dr.Table.Columns.Count - 1
  825.             Dim dc As DataColumn = dr.Table.Columns(i)
  826.             Dim colName As String = dc.ColumnName
  827.  
  828.             ' Check whether this column must be added to the SET part.
  829.             If dr(i).ToString <> dr(i, DataRowVersion.Original).ToString Then
  830.                 ' Add this column to the SET text.
  831.                 If setText.Length > 0 Then setText &= ","
  832.                 setText &= "[" & colName & "]=?"
  833.                 ' Add a corresponding parameter to the SET arraylist.
  834.                 param = New OleDbParameter(colName, dc.DataType)
  835.                 param.SourceVersion = DataRowVersion.Current
  836.                 param.Value = dr(i)
  837.                 setParams.Add(param)
  838.             End If
  839.  
  840.             ' Check whether this column must be added to the WHERE part.
  841.             ' (primary keys are always added to the WHERE part)
  842.             If colName = keyName Or dr(i).ToString <> dr(i, DataRowVersion.Original).ToString Then
  843.                 ' The column name is always added to the WHERE part.
  844.                 If whereText.Length > 0 Then whereText &= " AND "
  845.                 whereText &= "[" & colName & "]=?"
  846.                 ' Add a parameter in the corresponding position of the WHERE arraylist.
  847.                 param = New OleDbParameter(colName, dc.DataType)
  848.                 param.SourceVersion = DataRowVersion.Original
  849.                 param.Value = dr(i, DataRowVersion.Original)
  850.                 whereParams.Add(param)
  851.             End If
  852.         Next
  853.  
  854.         ' Assemble the SQL string.
  855.         Dim sql As String = "UPDATE " & dr.Table.TableName & " SET " & setText & " WHERE " & whereText
  856.         ' Create a command on the same connection as the original command.
  857.         Dim cmd As New OleDbCommand(sql, args.Command.Connection)
  858.         ' Enroll the new command in the same transaction as well
  859.         cmd.Transaction = args.Command.Transaction
  860.  
  861.         ' Assemble the collection of parameters.
  862.         ' First the SET parameters, then then WHERE parameters.
  863.         For Each param In setParams
  864.             cmd.Parameters.Add(param)
  865.         Next
  866.         For Each param In whereParams
  867.             cmd.Parameters.Add(param)
  868.         Next
  869.  
  870.         ' assign the the DataAdapter command.
  871.         args.Command = cmd
  872.     End Sub
  873.  
  874. End Class
  875.